#pragma once

#include <iostream>
#include <sys/socket.h>
#include <string>
#include <sys/types.h>
#include <cstring>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <functional>
#include <unistd.h>

namespace yui
{
    class TcpClient
    {
    public:
        TcpClient(std::string ip, uint16_t port)
            : serverIp_(ip), serverPort_(port)
        {
        }
        ~TcpClient()
        {
        }
        void InitClient()
        {
            sock_ = socket(AF_INET, SOCK_STREAM, 0);
            if (sock_ == -1)
            {
                perror("socket fail");
                exit(1);
            }
            std::cout << "Create sock Success!" << sock_ << std::endl;
        }
        void StartClient()
        {
            struct sockaddr_in server;
            socklen_t len = sizeof(server);
            bzero(&server, sizeof(server));
            server.sin_family = AF_INET;
            inet_aton(serverIp_.c_str(), &server.sin_addr);
            server.sin_port = htons(serverPort_);
            int cnt = 5;
            while (--cnt)
            {
                int ret = connect(sock_, (const struct sockaddr *)&server, len);
                if (ret == 0)
                {
                    break;
                }
                std::cerr << "网络异常，正在进行重连。。。剩余连接次数：" << cnt << std::endl;
                sleep(1);
            }
            if (cnt == 0)
            {
                perror("connect fail");
                close(sock_);
                exit(1);
            }
            std::cout << "connect success" << std::endl;

            Service();
        }
        void Service()
        {
            //std::cout<<"test"<<std::endl;
            char buff[1024];
            std::string who = serverIp_+"-"+std::to_string(serverPort_);
            while(true)
            {
                std::string msg;
                std::cout<<"Please Enter>>";
                std::getline(std::cin,msg);
                write(sock_,msg.c_str(),msg.size());
                //接受来自服务器的消息
                ssize_t n = read(sock_,buff,sizeof(buff)-1);
                if(n>0)
                {
                    buff[n] = '\0';
                    std::cout<<"Client get:"<<buff<<" from "<<who<<std::endl;
                }
                else if(n == 0)
                {
                    //读到文件末尾（服务器关闭了）
                    std::cout<<"Server "<<who<<" quit"<<std::endl;
                    close(sock_);
                    break;
                }
                else
                {
                    perror("read fail");
                    close(sock_);
                    break;
                }
            }
        }

    private:
        int sock_;
        std::string serverIp_;
        uint16_t serverPort_;
    };
}